package com.yuneec.fly.fragments;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

import com.yuneec.droneservice.ServiceManager;
import com.yuneec.droneservice.command.Calibrate;
import com.yuneec.droneservice.command.CommandListener;
import com.yuneec.droneservice.command.GetControllerType;
import com.yuneec.droneservice.command.GetControllerVersion;
import com.yuneec.droneservice.command.GetStatus;
import com.yuneec.droneservice.command.MAV_RC_ERROR_CODE;
import com.yuneec.droneservice.command.ReadSN;
import com.yuneec.droneservice.command.SendMd5;
import com.yuneec.droneservice.command.StartUpdate;
import com.yuneec.droneservice.command.TransFileData;
import com.yuneec.droneservice.command.WriteSN;
import com.yuneec.droneservice.model.ControllerVersion;
import com.yuneec.droneservice.model.PackageInfo;
import com.yuneec.droneservice.model.StatusInfo;
import com.yuneec.droneservice.request.IResponse;
import com.yuneec.fly.DroneApplication;
import com.yuneec.fly.GlobalParams;
import com.yuneec.fly.R;
import com.yuneec.fly.activities.CommandTestActivity;
import com.yuneec.fly.dialogs.BaseDialogFragment;
import com.yuneec.fly.dialogs.ProgressDialog;
import com.yuneec.fly.events.EventBusFactory;
import com.yuneec.fly.events.commandEvent.SendCommandEvent;
import com.yuneec.fly.events.uiEvent.ClickViewEvent;
import com.yuneec.fly.presenters.DronePresenter;
import com.yuneec.fly.utils.DialogHelper;
import com.yuneec.fly.utils.Md5;
import com.yuneec.fly.utils.SharePrefUtil;

import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by jw.gu on 2016/9/29 0029.
 */

public class ResetFragment extends BaseFragment {
    private static final int DISMISS_UPDATA_DIALOG = 1;
    private static final int SHOW_TOAST = 2;
    private Context context;
    private EditText snTxt;
    private Spinner mapSelectSpinner;
    private ProgressDialog progressDialog;
    private int queryStatusTimes = 0;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case DISMISS_UPDATA_DIALOG:
                    if (progressDialog != null) {
                        progressDialog.dismiss();
                    }
                    break;
                case SHOW_TOAST:
                    Toast.makeText(context, (String) msg.obj, Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    };

    @Override
    protected int getContentViewResourceId() {
        return R.layout.fragment_reset;
    }

    @Override
    public void init(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        context = getActivity();
        selfView.findViewById(R.id.resetGuide).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                DialogHelper.showConfirmDialog(getFragmentManager(), getString(R.string.confirm_message_reset_guide), new BaseDialogFragment.OnConfirmListener() {
                    @Override
                    public void onConfirm(BaseDialogFragment dialogFragment) {
                        dialogFragment.dismiss();
                        resetGuide();
                        Toast.makeText(context, R.string.reset_guide_success, Toast.LENGTH_SHORT).show();
                        if (GlobalParams.mapViewStatus == GlobalParams.ViewStatus.MINI) {
                            EventBusFactory.getUiBus().post(new ClickViewEvent(ClickViewEvent.ClickView.mapviewContainer));
                        } else if (GlobalParams.mapViewStatus == GlobalParams.ViewStatus.MIN) {
                            EventBusFactory.getUiBus().post(new ClickViewEvent(ClickViewEvent.ClickView.compassView));
                            EventBusFactory.getUiBus().post(new ClickViewEvent(ClickViewEvent.ClickView.mapviewContainer));
                        }
                    }
                });
            }
        });
        snTxt = (EditText) selfView.findViewById(R.id.sn_txt);
        selfView.findViewById(R.id.btn_getsn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ServiceManager.getInstance().sendDroneCommand(new ReadSN(), new CommandListener<String>() {
                    @Override
                    public void onSuccess(final IResponse<String> response) {
                        if (response == null || response.getCode() != MAV_RC_ERROR_CODE.MAV_RC_ERR_SUCCESS) {
                            handler.obtainMessage(SHOW_TOAST, "Get SN failed!!!   responseCode:" + (response == null ? "null" : response.getCode())).sendToTarget();
                        } else {
                            snTxt.post(new Runnable() {
                                @Override
                                public void run() {
                                    snTxt.setText(response.getParam());
                                }
                            });
                        }
                    }

                    @Override
                    public void onError(int errorCode) {
                        handler.obtainMessage(SHOW_TOAST, "Get SN errorCode:" + errorCode).sendToTarget();
                    }
                });
            }
        });
        selfView.findViewById(R.id.btn_setsn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ServiceManager.getInstance().sendDroneCommand(new WriteSN(snTxt.getText().toString()), new CommandListener() {
                    @Override
                    public void onSuccess(IResponse response) {
                        handler.obtainMessage(SHOW_TOAST, "Write SN ok!!!").sendToTarget();
                    }

                    @Override
                    public void onError(int errorCode) {
                        handler.obtainMessage(SHOW_TOAST, "Get SN errorCode:" + errorCode).sendToTarget();
                    }
                });
            }
        });
        selfView.findViewById(R.id.startCalibration).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                EventBusFactory.getCommandBus().post(new SendCommandEvent(Calibrate.startCalibrateCmd(), new CommandListener() {
                    @Override
                    public void onSuccess(IResponse response) {
                        handler.obtainMessage(SHOW_TOAST, "Start Calibration onSuccess").sendToTarget();
                    }

                    @Override
                    public void onTimeout() {
                        handler.obtainMessage(SHOW_TOAST, "Start Calibration onTimeout").sendToTarget();
                    }

                    @Override
                    public void onError(int errorCode) {
                        handler.obtainMessage(SHOW_TOAST, "Start Calibration onError").sendToTarget();
                    }
                }));
            }
        });
        selfView.findViewById(R.id.stopCalibration).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                EventBusFactory.getCommandBus().post(new SendCommandEvent(Calibrate.stopCalibrateCmd(), new CommandListener() {
                    @Override
                    public void onSuccess(IResponse response) {
                        handler.obtainMessage(SHOW_TOAST, "Stop Calibration onSuccess").sendToTarget();
                    }

                    @Override
                    public void onTimeout() {
                        handler.obtainMessage(SHOW_TOAST, "Stop Calibration onTimeout").sendToTarget();
                    }

                    @Override
                    public void onError(int errorCode) {
                        handler.obtainMessage(SHOW_TOAST, "Stop Calibration onError").sendToTarget();
                    }
                }));
            }
        });
        selfView.findViewById(R.id.update).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (progressDialog == null) {
                    progressDialog = new ProgressDialog();
                    progressDialog.setCancelable(false);
                }
                progressDialog.show(getFragmentManager(), "开始升级");
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        ControllerVersion version = null;
                        try {
                            version = getVersion();
                        } catch (Exception e) {
                            handler.obtainMessage(SHOW_TOAST, "获取版本信息出错！" + e.getMessage()).sendToTarget();
                        }
                        if (version != null) {
                            handler.obtainMessage(SHOW_TOAST, "获取版本信息：" + version.getFirmwareVersion()).sendToTarget();
                            String type = getType();
//                            String type = "123";
                            if (type != null) {
                                final File file = new File(Environment.getExternalStorageDirectory(), "update.lzo");
                                if (!(file.exists() && file.isFile())) {
                                    handler.sendEmptyMessage(DISMISS_UPDATA_DIALOG);
                                    handler.obtainMessage(SHOW_TOAST, "升级文件不存在,请把文件放在sd卡下,重命名为:update.lzo").sendToTarget();
                                    return;
                                }
                                PackageInfo packageInfo = new PackageInfo();
                                packageInfo.setMcuVersion(version.getMcuVersion());
                                packageInfo.setFirmwareVersion(version.getFirmwareVersion());
                                packageInfo.setHardwareVersion(version.getHardwareVersion());
                                packageInfo.setType(type);
                                packageInfo.setFilename("update.lzo");
                                packageInfo.setFileSize(file.length());
                                EventBusFactory.getCommandBus().post(new SendCommandEvent(new StartUpdate(packageInfo), new CommandListener() {
                                    @Override
                                    public void onSuccess(IResponse response) {
                                        byte[] tmpBuf;
                                        if (DroneApplication.getApplication().isMavLink) {
                                            tmpBuf = new byte[200];
                                        } else {
                                            tmpBuf = new byte[1024 * 2];
                                        }
                                        final byte[] buf = tmpBuf;
                                        try {
                                            final FileInputStream fis = new FileInputStream(file);
                                            final Runnable errorRun = new Runnable() {

                                                @Override
                                                public void run() {
                                                    handler.sendEmptyMessage(DISMISS_UPDATA_DIALOG);
                                                    handler.obtainMessage(SHOW_TOAST, "文件发送有不成功的！").sendToTarget();
                                                }
                                            };
                                            final Runnable successRun = new Runnable() {
                                                @Override
                                                public void run() {
                                                    new EventBusFactory().getCommandBus().post(new SendCommandEvent(new SendMd5(Md5.getFileMD5String(file)), new CommandListener() {
                                                        @Override
                                                        public void onSuccess(IResponse response) {
                                                            handler.obtainMessage(SHOW_TOAST, "文件传输和校验成功").sendToTarget();
                                                            GlobalParams.updating = true;
                                                            queryStatusTimes = 0;
                                                            queryUpdateStaus();
//                                                            selfView.getHandler().post(new Runnable() {
//                                                                @Override
//                                                                public void run() {
//                                                                    for (int i = 0; i < 12; i++) {
//                                                                        queryUpdateStaus();
//                                                                        handler.postDelayed(new Runnable() {
//                                                                            @Override
//                                                                            public void run() {
//                                                                                queryUpdateStaus();
//                                                                            }
//                                                                        },10000);
//                                                                    }
//                                                                    handler.sendEmptyMessage(DISMISS_UPDATA_DIALOG);
//                                                                }
//                                                            });

                                                        }

                                                        @Override
                                                        public void onTimeout() {
                                                            handler.sendEmptyMessage(DISMISS_UPDATA_DIALOG);
                                                            handler.obtainMessage(SHOW_TOAST, "md5校验失败，升级终止").sendToTarget();
                                                        }

                                                        @Override
                                                        public void onError(int errorCode) {
                                                            handler.sendEmptyMessage(DISMISS_UPDATA_DIALOG);
                                                            handler.obtainMessage(SHOW_TOAST, "md5校验失败，升级终止").sendToTarget();
                                                        }
                                                    }));
                                                }
                                            };
                                            int len = fis.read(buf);
                                            if (len > 0) {
                                                TransFileData transFileData = new TransFileData(0, buf, 0, len);
                                                transFileData(transFileData, new Runnable() {
                                                    int seq = 1;

                                                    @Override
                                                    public void run() {
                                                        Log.d("zzd_update", "send ok!");
                                                        try {
                                                            int len = fis.read(buf);
                                                            Log.d("zzd_update", String.format("read file len:%d", len));
                                                            if (len > 0) {
                                                                TransFileData transFileData = new TransFileData(seq++, buf, 0, len);
                                                                Log.d("zzd_update", String.format("send file seq:%d", transFileData.getSeq()));
                                                                transFileData(transFileData, this, errorRun);
                                                            } else {
                                                                successRun.run();
                                                            }
                                                        } catch (Exception e) {
                                                            handler.sendEmptyMessage(DISMISS_UPDATA_DIALOG);
                                                            handler.obtainMessage(SHOW_TOAST, "读取文件流出错！" + e.getMessage()).sendToTarget();
                                                            return;
                                                        }
                                                    }
                                                }, errorRun);
                                            }
                                        } catch (Exception e) {
                                            handler.sendEmptyMessage(DISMISS_UPDATA_DIALOG);
                                            handler.obtainMessage(SHOW_TOAST, "读取文件流出错！" + e.getMessage()).sendToTarget();
                                            return;
                                        }
                                    }
                                }));
                            } else {
                                handler.sendEmptyMessage(DISMISS_UPDATA_DIALOG);
                                handler.obtainMessage(SHOW_TOAST, "获取遥控器类型失败，升级终止").sendToTarget();
                            }
                        } else {
                            handler.sendEmptyMessage(DISMISS_UPDATA_DIALOG);
                            handler.obtainMessage(SHOW_TOAST, "获取版本信息失败，升级终止").sendToTarget();
                        }
                    }
                }).start();
            }
        });
        selfView.findViewById(R.id.testCommands).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(getActivity(), CommandTestActivity.class));
            }
        });
    }

    private void resetGuide() {
        SharePrefUtil.saveInt(context, SharePrefUtil.KEY.KEY_WAYPOINTS_GUIDE_SHOWED, 0);
        SharePrefUtil.saveInt(context, SharePrefUtil.KEY.KEY_FENCE_GUIDE_SHOWED, 0);
        SharePrefUtil.saveInt(context, SharePrefUtil.KEY.KEY_MAIN_GUIDE_SHOWED, 0);
    }

    private void transFileData(final TransFileData transFileData, final Runnable success, final Runnable error) {
        DronePresenter.getInstance().sendCommand(transFileData, new CommandListener() {
            int count = 0;

            @Override
            public void onSuccess(IResponse response) {
                success.run();
            }

            @Override
            public void onTimeout() {
                if (count < 3) {
                    count++;
                    DronePresenter.getInstance().sendCommand(transFileData, this);
                } else {
                    error.run();
                    Message msg = handler.obtainMessage(SHOW_TOAST, "传输文件 onTimeout");
                    handler.sendMessageDelayed(msg, 300);
                }
            }

            @Override
            public void onError(int errorCode) {
                if (count < 3) {
                    count++;
                    DronePresenter.getInstance().sendCommand(transFileData, this);
                } else {
                    error.run();
                    Message msg = handler.obtainMessage(SHOW_TOAST, "传输文件 onError" + errorCode);
                    handler.sendMessageDelayed(msg, 300);
                }
            }
        });
    }

//    private boolean transFileData(final TransFileData transFileData) {
//        final AtomicBoolean getResponse = new AtomicBoolean(false);
//        final AtomicBoolean result = new AtomicBoolean(false);
//        Log.d("zzd", "transFileData start");
//        EventBusFactory.getCommandBus().post(new SendCommandEvent(transFileData, new CommandListenerAdapter() {
//            @Override
//            public int getTimeout() {
//                return 5000;
//            }
//
//            @Override
//            public void onSuccess(BaseResponse response) {
//                result.set(true);
//                getResponse.set(true);
//                Log.d("zzd", "transFileData onSuccess");
//            }
//
//            @Override
//            public void onTimeout() {
//                getResponse.set(true);
//                progressDialog.dismiss();
//                Log.d("zzd", "transFileData onTimeout");
//            }
//
//            @Override
//            public void onError(int errorCode) {
//                getResponse.set(true);
//                progressDialog.dismiss();
//                Log.d("zzd", "transFileData onError");
//            }
//        }));
//        for (int i = 0; i < 1000; i++) {
//            if (getResponse.get()) {
//                Log.d("zzd", "transFileData 发送结束:" + result.get());
//                break;
//            }
//            SystemClock.sleep(50);
//        }
//        return result.get();
//    }

    private void queryUpdateStaus() {
        handler.obtainMessage(SHOW_TOAST, "queryUpdateStaus").sendToTarget();
        EventBusFactory.getCommandBus().post(new SendCommandEvent(new GetStatus(), new CommandListener<StatusInfo>() {
            @Override
            public long getTimeout() {
                return 2000;
            }

            @Override
            public void onSuccess(IResponse<StatusInfo> response) {
                queryStatusTimes++;
                StatusInfo statusInfo = response.getParam();
                handler.obtainMessage(SHOW_TOAST, "Upgrade State : " + statusInfo.getUpgradeState()).sendToTarget();
                handler.removeMessages(DISMISS_UPDATA_DIALOG);
                handler.sendEmptyMessageDelayed(DISMISS_UPDATA_DIALOG, 300000 - queryStatusTimes * 10000);
            }

            @Override
            public void onError(int errorCode) {
                handler.obtainMessage(SHOW_TOAST, "Upgrade State query onError " + errorCode).sendToTarget();
                errDo();
            }

            @Override
            public void onTimeout() {
                handler.obtainMessage(SHOW_TOAST, "Upgrade State query onTimeout ").sendToTarget();
                errDo();
            }

            void errDo() {
                if (queryStatusTimes < 30) {
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            queryUpdateStaus();
                        }
                    }, 10000);
                } else {
                    handler.obtainMessage(SHOW_TOAST, "Upgrade State query timeout with 5 minutes").sendToTarget();
                    handler.sendEmptyMessage(DISMISS_UPDATA_DIALOG);
                }
                queryStatusTimes++;
            }
        }));
    }

    private ControllerVersion getVersion() {
        final ControllerVersion[] version = new ControllerVersion[1];
        final AtomicBoolean getResponse = new AtomicBoolean(false);
        Log.d("zzd", "getVersion start");
        EventBusFactory.getCommandBus().post(new SendCommandEvent(new GetControllerVersion(), new CommandListener<ControllerVersion>() {
            @Override
            public void onSuccess(IResponse<ControllerVersion> response) {
                version[0] = response.getParam();
                getResponse.set(true);
                Log.d("zzd", "getVersion onSuccess");
            }

            @Override
            public void onError(int errorCode) {
                getResponse.set(true);
                Log.d("zzd", "getVersion onError");
            }

            @Override
            public void onTimeout() {
                getResponse.set(true);
                Log.d("zzd", "getVersion onTimeout");
            }
        }));
        for (int i = 0; i < 50; i++) {
            if (getResponse.get()) {
                Log.d("zzd", "getVersion 发送结束:" + version[0]);
                break;
            }
            SystemClock.sleep(20);
        }
        return version[0];
    }

    private String getType() {
        final String[] type = new String[1];
        final boolean[] getResponse = new boolean[1];
        EventBusFactory.getCommandBus().post(new SendCommandEvent(new GetControllerType(), new CommandListener<String>() {
            @Override
            public void onSuccess(IResponse<String> response) {
                type[0] = response.getParam();
                getResponse[0] = true;
            }

            @Override
            public void onError(int errorCode) {
                getResponse[0] = true;
            }

            @Override
            public void onTimeout() {
                getResponse[0] = true;
            }
        }));
        for (int i = 0; i < 50; i++) {
            if (getResponse[0]) {
                break;
            }
            SystemClock.sleep(20);
        }
        return type[0];
    }
}
